<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Fabric.js自由画笔圈涂功能</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        #canvas-container {
            border: 1px solid #ccc;
            margin-bottom: 20px;
            width: 800px;
            height: 600px;
        }
        .controls {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin-bottom: 10px;
        }
        button {
            padding: 8px 16px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        button:hover {
            background-color: #45a049;
        }
        .tool-option {
            display: flex;
            align-items: center;
            gap: 5px;
        }
    </style>
</head>
<body>
    <h3>Fabric.js自由画笔圈涂功能</h3>
    <div class="controls">
        <button id="brushBtn">画笔模式</button>
        <button id="fillBtn">填充区域</button>
        <button id="clearBtn">清除所有</button>
        <div class="tool-option">
            <label for="brushColor">画笔颜色:</label>
            <input type="color" id="brushColor" value="#000000">
        </div>
        <div class="tool-option">
            <label for="brushSize">画笔大小:</label>
            <input type="range" id="brushSize" min="1" max="20" value="5">
        </div>
        <div class="tool-option">
            <label for="fillColor">填充颜色:</label>
            <input type="color" id="fillColor" value="#ff0000">
        </div>
    </div>
    <div id="canvas-container">
        <canvas id="fabricCanvas" width="800" height="600"></canvas>
    </div>
    <p>使用方法: 选择画笔模式，在画布上自由绘制封闭图形，然后点击填充区域按钮。</p>
    
    <script>
        // 初始化画布
        const canvas = new fabric.Canvas('fabricCanvas');
        
        // 状态变量
        let mode = 'brush'; // 'brush' 或 'fill'
        let brushColor = '#000000';
        let brushSize = 5;
        let fillColor = '#ff0000';
        let paths = []; // 存储所有绘制的路径
        
        // 获取DOM元素
        const brushBtn = document.getElementById('brushBtn');
        const fillBtn = document.getElementById('fillBtn');
        const clearBtn = document.getElementById('clearBtn');
        const brushColorInput = document.getElementById('brushColor');
        const brushSizeInput = document.getElementById('brushSize');
        const fillColorInput = document.getElementById('fillColor');
        
        // 设置画笔颜色
        brushColorInput.addEventListener('input', function() {
            brushColor = this.value;
            canvas.freeDrawingBrush.color = brushColor;
        });
        
        // 设置画笔大小
        brushSizeInput.addEventListener('input', function() {
            brushSize = parseInt(this.value);
            canvas.freeDrawingBrush.width = brushSize;
        });
        
        // 设置填充颜色
        fillColorInput.addEventListener('input', function() {
            fillColor = this.value;
        });
        
        // 初始化画笔设置
        canvas.freeDrawingBrush.color = brushColor;
        canvas.freeDrawingBrush.width = brushSize;
        
        // 画笔模式按钮事件
        brushBtn.addEventListener('click', function() {
            mode = 'brush';
            canvas.isDrawingMode = true; // 启用Fabric.js原生绘图模式
            canvas.defaultCursor = 'crosshair';
            alert('画笔模式已激活，请在画布上自由绘制。');
        });
        
        // 填充区域按钮事件 - 精确定位修复
        fillBtn.addEventListener('click', function() {
            if (canvas.getObjects().length === 0) {
                alert('请先绘制封闭图形。');
                return;
            }
            
            // 获取最后绘制的路径
            const lastPath = canvas.getObjects().slice(-1)[0];
            
            // 确保是路径对象
            if (lastPath && lastPath.type === 'path') {
                // 简化判断：如果路径首尾接近，则认为是封闭的
                const pathCoords = lastPath.path;
                if (pathCoords.length >= 4) { // 至少需要一个起点和两个点
                    const firstPoint = { x: pathCoords[0][1], y: pathCoords[0][2] };
                    const lastPoint = { x: pathCoords[pathCoords.length - 1][1], y: pathCoords[pathCoords.length - 1][2] };
                    
                    const distance = Math.sqrt(
                        Math.pow(lastPoint.x - firstPoint.x, 2) + 
                        Math.pow(lastPoint.y - firstPoint.y, 2)
                    );
                    
                    if (distance < 20) { // 距离阈值
                        // 获取路径边界框
                        const bounds = lastPath.getBoundingRect();
                        
                        // 创建填充多边形 - 使用正确的坐标转换
                        const points = [];
                        for (let i = 0; i < pathCoords.length; i++) {
                            // 将路径坐标转换为画布坐标
                            const p = new fabric.Point(pathCoords[i][1], pathCoords[i][2]);
                            const transformedPoint = fabric.util.transformPoint(
                                p,
                                lastPath.calcTransformMatrix()
                            );
                            
                            // 修正坐标，考虑路径的位置和旋转
                            points.push({ 
                                x: transformedPoint.x - bounds.left, 
                                y: transformedPoint.y - bounds.top 
                            });
                        }
                        
                        // 创建多边形并设置与原路径相同的位置和变换
                        const polygon = new fabric.Polygon(points, {
                            left: bounds.left,
                            top: bounds.top,
                            fill: fillColor,
                            opacity: 0.5,
                            stroke: null,
                            selectable: false,
                            angle: lastPath.angle,
                            scaleX: lastPath.scaleX,
                            scaleY: lastPath.scaleY
                        });
                        
                        canvas.add(polygon);
                        canvas.renderAll();
                        alert('区域已填充。');
                    } else {
                        alert('图形未闭合，请继续绘制或重新开始。');
                    }
                } else {
                    alert('图形未闭合，请继续绘制或重新开始。');
                }
            } else {
                alert('请先绘制封闭图形。');
            }
        });
        
        // 清除所有按钮事件
        clearBtn.addEventListener('click', function() {
            canvas.clear();
            canvas.isDrawingMode = false;
            canvas.defaultCursor = 'default';
        });
        
        // 监听路径创建完成事件
        canvas.on('path:created', function(options) {
            paths.push(options.path);
        });
    </script>
</body>
</html>